using System;
using System.Collections;
using System.Text;
using System.Windows.Forms;
using NewLife.Net;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        private NetServer _server;

        public Form1()
        {
            InitializeComponent();
            StartTcpServer(6600); // 设置端口号
        }

        private void StartTcpServer(int port)
        {
            _server = new NetServer
            {
                Port = port
            };

            _server.NewSession += (s, e) =>
            {
                var session = e.Session;
                session.Received += (s1, e1) =>
                {
                    //var receivedMessage = Encoding.UTF8.GetString(e1.Packet.ToArray());
                    var receivedMessage1 = BitConverter.ToString(e1.Packet.ToArray()).Replace("-", "");
                    textBox1.Invoke((MethodInvoker)delegate
                    {
                        textBox1.AppendText($"Received from {session.Remote}: {receivedMessage1}{Environment.NewLine}");
                    });
                    var receivedMessage = e1.Packet.ToArray();
                    var protocolMessage = ProtocolMessage.FromArray(receivedMessage);

                    textBox1.Invoke((MethodInvoker)delegate
                    {
                        textBox1.AppendText($"Received from {session.Remote}: {BitConverter.ToString(receivedMessage)}{Environment.NewLine}");
                    });

                    // 根据功能码处理不同类型的操作
                    switch (protocolMessage.FunctionCode)
                    {
                        case 0x01:
                            HandleReadCoils(protocolMessage, session);
                            break;
                        case 0x02:
                            HandleReadDiscreteInputs(protocolMessage, session);
                            break;
                        case 0x03:
                            HandleReadHoldingRegisters(protocolMessage, session);
                            break;
                        case 0x04:
                            HandleReadInputRegisters(protocolMessage, session);
                            break;
                        case 0x05:
                            HandleWriteSingleCoil(protocolMessage, session);
                            break;
                        case 0x0F:
                            HandleWriteMultipleCoils(protocolMessage, session);
                            break;
                        case 0x06:
                            HandleWriteSingleRegister(protocolMessage, session);
                            break;
                        case 0x10:
                            HandleWriteMultipleRegisters(protocolMessage, session);
                            break;
                        case 0x45:
                            HandleReportMultipleCoils(protocolMessage, session);
                            break;

                        case 0x42:
                            HandleReportMultipleDiscreteRegisters(protocolMessage, session);
                            break;

                        case 0x46:
                            HandleReportMultipleHoldingRegisters(protocolMessage, session);
                            break;

                        case 0x44:
                            HandleReportMultipleInputRegisters(protocolMessage, session);
                            break;

                        case 0x48:
                            HandleDeviceTimeCalibration(protocolMessage, session);
                            break;

                        default:
                            textBox1.Invoke((MethodInvoker)delegate
                            {
                                textBox1.AppendText($"Unknown function code: {protocolMessage.FunctionCode}{Environment.NewLine}");
                            });
                            break;
                    }
                };

                textBox1.Invoke((MethodInvoker)delegate
                {
                    textBox1.AppendText($"New client connected: {session.Remote}\r\n");
                });
            };

        

            _server.Start();
            textBox1.AppendText($"TCP Server started on port {port}.\r\n");
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _server?.Dispose();
        }
        private void HandleReadCoils(ProtocolMessage message, INetSession session)
        {
            // 示例：假设我们有一个固定的线圈状态数组
            bool[] coilStatus = new bool[] { true, true, false, false, true, true, true, true, true, true };

            // 计算需要返回的字节数
            int byteCount = (message.RegisterLength + 7) / 8;
            byte[] data = new byte[byteCount];

            for (int i = 0; i < message.RegisterLength; i++)
            {
                if (coilStatus[message.RegisterStartAddress + i])
                {
                    data[i / 8] |= (byte)(1 << (i % 8));
                }
            }

            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, data);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }
        private void HandleWriteSingleCoil(ProtocolMessage message, INetSession session)
        {
            // 示例：假设我们有一个固定的线圈状态数组
            bool[] coilStatus = new bool[100];

            // 更新线圈状态
            bool newState = message.Data[0] == 0xFF;
            coilStatus[message.RegisterStartAddress] = newState;

            // 响应消息
            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, message.Data);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }
        private void HandleWriteMultipleCoils(ProtocolMessage message, INetSession session)
        {
            // 示例：假设我们有一个固定的线圈状态数组
            bool[] coilStatus = new bool[100];

            for (int i = 0; i < message.RegisterLength; i++)
            {
                bool newState = (message.Data[i / 8] & (1 << (i % 8))) != 0;
                coilStatus[message.RegisterStartAddress + i] = newState;
            }

            // 响应消息
            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, new byte[0]);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }
        private void HandleReadDiscreteInputs(ProtocolMessage message, INetSession session)
        {
            // 示例：假设我们有一个固定的离散输入状态数组
            bool[] inputStatus = new bool[] { true, false, true, false, true, false, true, false, true, false };

            // 计算需要返回的字节数
            int byteCount = (message.RegisterLength + 7) / 8;
            byte[] data = new byte[byteCount];

            for (int i = 0; i < message.RegisterLength; i++)
            {
                if (inputStatus[message.RegisterStartAddress + i])
                {
                    data[i / 8] |= (byte)(1 << (i % 8));
                }
            }

            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, data);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }
        private void HandleReadHoldingRegisters(ProtocolMessage message, INetSession session)
        {
            // 示例：假设我们有一个固定的保持寄存器数组
            ushort[] holdingRegisters = new ushort[] { 555, 0, 100 };

            byte[] data = new byte[message.RegisterLength * 2];
            for (int i = 0; i < message.RegisterLength; i++)
            {
                data[i * 2] = (byte)(holdingRegisters[message.RegisterStartAddress + i] >> 8);
                data[i * 2 + 1] = (byte)(holdingRegisters[message.RegisterStartAddress + i] & 0xFF);
            }

            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, data);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }
        private void HandleWriteSingleRegister(ProtocolMessage message, INetSession session)
        {
            // 示例：假设我们有一个固定的保持寄存器数组
            ushort[] holdingRegisters = new ushort[100];

            // 更新寄存器值
            holdingRegisters[message.RegisterStartAddress] = (ushort)((message.Data[0] << 8) | message.Data[1]);

            // 响应消息
            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, message.Data);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }
        private void HandleWriteMultipleRegisters(ProtocolMessage message, INetSession session)
        {
            // 示例：假设我们有一个固定的保持寄存器数组
            ushort[] holdingRegisters = new ushort[100];

            for (int i = 0; i < message.RegisterLength; i++)
            {
                holdingRegisters[message.RegisterStartAddress + i] = (ushort)((message.Data[i * 2] << 8) | message.Data[i * 2 + 1]);
            }

            // 响应消息
            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, new byte[0]);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }
        private void HandleReadInputRegisters(ProtocolMessage message, INetSession session)
        {
            // 示例：假设我们有一个固定的输入寄存器数组
            ushort[] inputRegisters = new ushort[] { 10 };

            byte[] data = new byte[message.RegisterLength * 2];
            for (int i = 0; i < message.RegisterLength; i++)
            {
                data[i * 2] = (byte)(inputRegisters[message.RegisterStartAddress + i] >> 8);
                data[i * 2 + 1] = (byte)(inputRegisters[message.RegisterStartAddress + i] & 0xFF);
            }

            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, data);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }

        private void HandleReportMultipleCoils(ProtocolMessage message, INetSession session)
        {
            // 处理上报多个线圈的逻辑
            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, new byte[0]);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }

        private void HandleReportMultipleDiscreteRegisters(ProtocolMessage message, INetSession session)
        {
            // 处理上报多个离散寄存器的逻辑
            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, new byte[0]);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }

        private void HandleReportMultipleHoldingRegisters(ProtocolMessage message, INetSession session)
        {
            // 处理上报多个保持寄存器的逻辑
            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, new byte[0]);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }

        private void HandleReportMultipleInputRegisters(ProtocolMessage message, INetSession session)
        {
            // 处理上报多个输入寄存器的逻辑
            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, message.RegisterStartAddress, message.RegisterLength, new byte[0]);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }

        private void HandleDeviceTimeCalibration(ProtocolMessage message, INetSession session)
        {
            // 处理设备校时的逻辑
            var timestamp = BitConverter.GetBytes((uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds());
            var responseMessage = new ProtocolMessage(message.DeviceId, message.FunctionCode, 0, 0, timestamp);
            var responseBytes = responseMessage.ToArray();
            session.Send(responseBytes);
        }
    }
}

public class ProtocolMessage
{
    public byte DeviceId { get; set; }
    public byte FunctionCode { get; set; }
    public ushort RegisterStartAddress { get; set; }
    public ushort RegisterLength { get; set; }
    public byte[] Data { get; set; }
    public ushort Crc { get; set; }

    public ProtocolMessage(byte deviceId, byte functionCode, ushort registerStartAddress, ushort registerLength, byte[] data)
    {
        DeviceId = deviceId;
        FunctionCode = functionCode;
        RegisterStartAddress = registerStartAddress;
        RegisterLength = registerLength;
        Data = data;
        Crc = CalculateCrc();
    }

    public byte[] ToArray()
    {
        var message = new byte[7 + 1];
        message[0] = DeviceId;
        message[1] = FunctionCode;
        message[2] = (byte)(RegisterStartAddress >> 8);
        message[3] = (byte)(RegisterStartAddress & 0xFF);
        message[4] = (byte)(RegisterLength >> 8);
        message[5] = (byte)(RegisterLength & 0xFF);
        message[6] = (byte)Data.Length;
        Array.Copy(Data, 0, message, 7, Data.Length);
        var crcBytes = BitConverter.GetBytes(Crc);
        Array.Copy(crcBytes, 0, message, message.Length - 2, 2);
        return message;
    }

    public static ProtocolMessage FromArray(byte[] array)
    {
        if (array.Length < 7) throw new ArgumentException("Invalid message length");

        var deviceId = array[0];
        var functionCode = array[1];
        var registerStartAddress = (ushort)((array[2] << 8) | array[3]);
        var registerLength = (ushort)((array[4] << 8) | array[5]);
        var dataLength = array[6];
        var data = new byte[dataLength];
        Array.Copy(array, 7, data, 0, dataLength);
        var crc = BitConverter.ToUInt16(array, array.Length - 2);

        return new ProtocolMessage(deviceId, functionCode, registerStartAddress, registerLength, data) { Crc = crc };
    }

    private ushort CalculateCrc()
    {
        // CRC计算逻辑
        ushort crc = 0xFFFF;
        var message = new byte[7 + Data.Length];
        message[0] = DeviceId;
        message[1] = FunctionCode;
        message[2] = (byte)(RegisterStartAddress >> 8);
        message[3] = (byte)(RegisterStartAddress & 0xFF);
        message[4] = (byte)(RegisterLength >> 8);
        message[5] = (byte)(RegisterLength & 0xFF);
        message[6] = (byte)Data.Length;
        Array.Copy(Data, 0, message, 7, Data.Length);

        for (int pos = 0; pos < message.Length; pos++)
        {
            crc ^= (ushort)message[pos];
            for (int i = 8; i != 0; i--)
            {
                if ((crc & 0x0001) != 0)
                {
                    crc >>= 1;
                    crc ^= 0xA001;
                }
                else
                {
                    crc >>= 1;
                }
            }
        }
        return crc;
    }
}